package nsip.components.ds;

import nsip.util.LazyInitializingMap;

/**
 * An inventory map which can be used to manage items identified by a specified
 * key. The inventory of items may not become negative by removing items via
 * {@link SimpleInventoryMap#remove(java.lang.Object, int)} but by adding a
 * negative amout via {@link SimpleInventoryMap#add(java.lang.Object, int)}. 
 * 
 * @author nico.rehwaldt
 */
public class SimpleInventoryMap<T> extends LazyInitializingMap<T, Integer> {

    @Override
    protected Integer initialize(Object key) {
        return 0;
    }

    /**
     * Adds the value to the inventory entry with the specified key and
     * returns the new value
     *
     * @param key
     * @param value
     *
     * @return new amount of the specified key in the inventory
     */
    public int add(T key, int value) {
        int result = get(key) + value;
        put(key, result);
        return result;
    }

    /**
     * Removes an amount of elements from this inventory and returns the
     * reminder (the amount >= 0 which was not present in the inventory
     * and thus could not be removed).
     *
     * @param key
     * @param amount
     *
     * @return amount of the key which could not be removed cause
     *         it was not present
     */
    public int remove(T key, int amount) {
        if (amount < 0) {
            throw new IllegalArgumentException("Amount may not be negative");
        }
        
        int currentDemand = get(key);
        if (currentDemand < 0) {
            return amount;
        }

        int result = currentDemand - amount;
        put(key, result > 0 ? result : 0);
        return result > 0 ? 0 : -result;
    }

    /**
     * Performs an add operation for the given amount on all keys and
     * returns the results of all operations.
     *
     * @param keys
     * @param value
     * @return
     */
    public int[] addAll(T[] keys, int value) {
        int[] results = new int[keys.length];
        for (int i = 0; i < keys.length; i++) {
            results[i] = add(keys[i], value);
        }
        return results;
    }

    /**
     * Performes a remove operation for the given amount on all keys and
     * returns the result of all operations.
     *
     * @param keys
     * @param value
     * @return
     */
    public int[] removeAll(T[] keys, int value) {
        int[] results = new int[keys.length];
        for (int i = 0; i < keys.length; i++) {
            results[i] = remove(keys[i], value);
        }
        return results;
    }
}
